package com.kafeblog.roo.portletmvc.liferay;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.Validate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.process.manager.FileManager;
import org.springframework.roo.process.manager.MutableFile;
import org.springframework.roo.project.Dependency;
import org.springframework.roo.project.DependencyScope;
import org.springframework.roo.project.DependencyType;
import org.springframework.roo.project.Path;
import org.springframework.roo.project.PathResolver;
import org.springframework.roo.project.ProjectOperations;
import org.springframework.roo.project.Property;
import org.springframework.roo.support.logging.HandlerUtils;
import org.springframework.roo.support.util.FileUtils;
import org.springframework.roo.support.util.XmlUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.kafeblog.roo.portletmvc.PortletmvcOperations;


@Component
@Service
public class LiferayOperationsImpl implements LiferayOperations {
	
	private Logger log = HandlerUtils.getLogger(getClass());
	
    @Reference protected FileManager fileManager;
	@Reference protected PathResolver pathResolver;
	
	@Reference protected ProjectOperations projectOperations;
	@Reference protected PortletmvcOperations portletmvcOperations;
	
	@Override
	public void configureLiferayPortal(String liferayVersion) {
		updateMavenDependencies(liferayVersion);
		createOrUpdateLiferayDisplayXml();
		createOrUpdateLiferayPortletXml();
		createOrUpdateLiferayPluginPackageProperties();
	}
	@Override
	public boolean isLiferayCommandAvailable() {
		return portletmvcOperations.isPortletInstalled();
		
	}
	@Override
	public void updateLiferayDisplayXml(JavaType controller, String category) {
		String portletName = controller.getSimpleTypeName();
		log.info("updateLiferayDisplayXml");
		 createOrUpdateLiferayDisplayXml(category, portletName);
	}
	@Override
	public void updateLiferayPortletXml(JavaType controller,
			String displayName, String supportModes) {
		log.info("updateLiferayPortletXml");
		String portletName = controller.getSimpleTypeName();
		createOrUpdateLiferayPortletXml(portletName);
	}	
	private void createOrUpdateLiferayPluginPackageProperties() {
		final InputStream in = FileUtils.getInputStream(getClass(), LiferayConstant.LIFERAY_PLUGIN_PACKAGE_PROPERTIES);
		final String fileIdentifier = pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/" + LiferayConstant.LIFERAY_PLUGIN_PACKAGE_PROPERTIES);
		MutableFile file = fileManager.createFile(fileIdentifier);
		final OutputStream out = file.getOutputStream();
		try{
			IOUtils.copy(in, out);
			log.warning("Generated liferay-plugin-package.properties in WEB-INF. Please update the file with appropriate information.");
			log.warning("Sample liferay-plugin-package.properties file: https://gist.github.com/khoinguyen/6137339");
		} catch (final IOException ignored){
			
		} finally {
			IOUtils.closeQuietly(in);
			IOUtils.closeQuietly(out);
		}
	}
	private void createOrUpdateLiferayPortletXml() {
		createOrUpdateLiferayPortletXml(null);
	}
	private void createOrUpdateLiferayPortletXml(String portletName) {
		final String fileIdentifier = pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/" + LiferayConstant.LIFERAY_PORTLET_XML);
		
		InputStream input = null;
		Document document = null;
		if (!fileManager.exists(fileIdentifier)) {
			input = FileUtils.getInputStream(
	                getClass(), LiferayConstant.LIFERAY_PORTLET_XML);
		} else {
			input = fileManager.getInputStream(fileIdentifier);
		}
		document = XmlUtils.readXml(input);
        
		if (portletName != null && !portletName.equals("")) {
			// check if portletName existed, create new <portlet> if not existed

	        Element root = (Element)document.getFirstChild();
	        
	        Element portletEl = XmlUtils.findFirstElement("/liferay-portlet-app/portlet[portlet-name=\""+portletName+"\"]", root);
	        if (portletEl == null) {
	        	portletEl = document.createElement("portlet");
	        	portletEl.appendChild(XmlUtils.createTextElement(document, "portlet-name", portletName));
	        	portletEl.appendChild(XmlUtils.createTextElement(document, "icon", "/icon.png"));
	        	portletEl.appendChild(XmlUtils.createTextElement(document, "instanceable", "false"));
	        	portletEl.appendChild(XmlUtils.createTextElement(document, "header-portlet-css", "/css/main.css"));
	        	portletEl.appendChild(XmlUtils.createTextElement(document, "footer-portlet-javascript", "/js/main.js"));
	        	
	        	root.appendChild(portletEl);
	        }
		}
		
		fileManager.createOrUpdateTextFileIfRequired(fileIdentifier,
                XmlUtils.nodeToString(document), true);
	}
	private void createOrUpdateLiferayDisplayXml() {
		createOrUpdateLiferayDisplayXml(null, null);
	}
	private void createOrUpdateLiferayDisplayXml(String category, String portletName) {
		
		final String fileIdentifier = pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/" + LiferayConstant.LIFERAY_DISPLAY_XML);
		
		InputStream input = null;
		Document document = null;
		if (!fileManager.exists(fileIdentifier)) {
			input = FileUtils.getInputStream(
	                getClass(), LiferayConstant.LIFERAY_DISPLAY_XML);
		} else {
			input = fileManager.getInputStream(fileIdentifier);
		}
		document = XmlUtils.readXml(input);
        
		if (category != null && !category.equals("")) {

	        Element root = (Element)document.getFirstChild();
			// create new category if not existed
			Element categoryEl = XmlUtils.findFirstElement("/display/category[@name=\""+category+"\"]", root);
			
			if (categoryEl == null) {
				// not found
				categoryEl = document.createElement("category");
				categoryEl.setAttribute("name", category);
				root.appendChild(categoryEl);
			}
			if (portletName != null && !portletName.equals("")) {
				// add <portlet> to correspondance <category> if not existed
				Element portletEl = XmlUtils.findFirstElement("portlet[@id=\""+portletName+"\"]", categoryEl);
				if (portletEl == null) {
					portletEl = document.createElement("portlet");
					portletEl.setAttribute("id", portletName);
					categoryEl.appendChild(portletEl);
				}
			}
		}
		
		
		fileManager.createOrUpdateTextFileIfRequired(fileIdentifier,
                XmlUtils.nodeToString(document), true);
	}

	private void updateMavenDependencies(String liferayVersion) {
		final String moduleName = projectOperations.getFocusedModuleName();
		
		projectOperations.addProperty(moduleName, new Property("liferay.version", liferayVersion));
		
		List<Dependency> dependencies = new ArrayList<Dependency>();
		dependencies.add(new Dependency("com.liferay.portal", "portal-service", "${liferay.version}", DependencyType.JAR, DependencyScope.PROVIDED));
		dependencies.add(new Dependency("com.liferay.portal", "util-bridges", "${liferay.version}", DependencyType.JAR, DependencyScope.PROVIDED));
		dependencies.add(new Dependency("com.liferay.portal", "util-taglib", "${liferay.version}", DependencyType.JAR, DependencyScope.PROVIDED));
		dependencies.add(new Dependency("com.liferay.portal", "util-java", "${liferay.version}", DependencyType.JAR, DependencyScope.PROVIDED));
		projectOperations.addDependencies(moduleName, dependencies);
	}



}
